package com.easylinkin.linkappapi.lobar.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.easylinkin.linkappapi.annotation.CommonOperateLogAnnotate;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.utils.async.AsyncUtil;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.lobar.dto.UserProjectDTO;
import com.easylinkin.linkappapi.lobar.dto.excel.ExcelResultDTO;
import com.easylinkin.linkappapi.lobar.entity.UserProject;
import com.easylinkin.linkappapi.lobar.entity.emp.EmpUserBase;
import com.easylinkin.linkappapi.lobar.entity.emp.EmpUserBaseDTO;
import com.easylinkin.linkappapi.lobar.service.UserProjectService;
import com.easylinkin.linkappapi.lobar.util.UnZipUtils;
import com.easylinkin.linkappapi.lobar.util.UnzipFileVo;
import com.easylinkin.linkappapi.operatelog.LogHelper;
import com.easylinkin.linkappapi.operatelog.constant.LogConstant.LogModule;
import com.easylinkin.linkappapi.operatelog.constant.LogConstant.LogOperateType;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import jodd.util.StringUtil;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;
import sun.misc.BASE64Encoder;

/**
 * @author: kan yuanfeng
 * @Date: 2020/11/04 11:42
 * @Description: 项目用户管理
 */
@RestController
@RequestMapping("userProject")
@Api(tags = "项目用户管理")
public class UserProjectController {
  
  @Autowired
  private UserProjectService userProjectService;
  @Autowired
  private ResourceLoader resourceLoader;
  @Value("${photo.cache.directory}")
  private String photoDir;
  @Autowired
  private LinkappUserContextProducer linkappUserContextProducer;

  /**
   * @Description: 增加用户
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping
  @ApiOperation("增加用户")
  public RestMessage insert(@RequestBody UserProject userProject){
    //todo 参数验证
    userProjectService.insert(userProject);
    return RestBuilders.successBuilder().build();
  }

  /**
   * 修改教育状态
   * @param userProject
   * @return
   */
  @PostMapping("updateEduState")
  @ApiOperation("增加用户")
  public RestMessage updateEduState(@RequestBody UserProject userProject){
    //todo 参数验证
    userProjectService.updateEduState(userProject);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 增加用户(同步emp)
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("emp")
  @ApiOperation("增加用户")
  public RestMessage insertEmp(@RequestBody EmpUserBaseDTO empUserBaseDTO){
    //todo 参数验证
    userProjectService.insertEmp(empUserBaseDTO);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 删除用户（包含批量删除）
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @DeleteMapping
  @ApiOperation("删除用户（包含批量删除）")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage delBatch(@RequestBody UserProject userProject){
    Assert.notEmpty(userProject.getIds(),"id不能为空");
    // 记录日志详情
    List<String> empUserBases = new ArrayList<>();
    userProject.getIds().forEach(p->{
      EmpUserBase empUserBase = userProjectService.getByIdEmp(p);
      empUserBases.add(empUserBase.getCard());
    });
    if(CollectionUtil.isNotEmpty(empUserBases)){
      LogHelper.setContent(LogOperateType.LABOL_USER_DELETE, StringUtil.join(empUserBases,","));
    }
    userProjectService.delBatch(userProject.getIds());
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 编辑用户
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PutMapping
  @ApiOperation("编辑用户")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage updateById(@RequestBody UserProject userProject){
    Assert.notNull(userProject.getId(),"id不能为空");
    // 记录日志详情
    EmpUserBase empUserBase = userProjectService.getByIdEmp(userProject.getId());
    String code = LogOperateType.LABOL_USER_UPDATE;
    if(null != userProject.getStatus()&&Integer.valueOf(0).equals(userProject.getStatus())){
      code = LogOperateType.LABOL_USER_EXIT_PROJECT;
    }
    LogHelper.setContent(code,empUserBase.getCard());
    userProjectService.updateOne(userProject);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 下发到闸机
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PutMapping("upToGate")
  @ApiOperation("下发到闸机")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage upToGate(@RequestBody UserProject userProject){
    Assert.notNull(userProject.getId(),"id不能为空");
    // 记录日志详情
    EmpUserBase empUserBase = userProjectService.getByIdEmp(userProject.getId());
    LogHelper.setContent(LogOperateType.LABOL_USER_UP_TO_GATE,empUserBase.getCard());
    Map<String, Object> map = userProjectService.upToGate(userProject.getId());
    //是否直接抛异常
    if (Boolean.TRUE.equals(map.get("show"))){
      throw new BusinessException((String) map.get("msg"));
    }
    return RestBuilders.successBuilder().data(map).build();
  }

  /**
   * @Description: 编辑用户(emp)
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PutMapping("emp")
  @ApiOperation("编辑用户")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage updateByIdEmp(@RequestBody EmpUserBaseDTO empUserBaseDTO){
    Assert.notNull(empUserBaseDTO.getId(),"id不能为空");
    // 记录日志详情
    EmpUserBase empUserBase = userProjectService.getByIdEmp(empUserBaseDTO.getUserProject().getId());
    String code = LogOperateType.LABOL_USER_UPDATE;
    LogHelper.setContent(code,empUserBase.getCard());
    userProjectService.updateByIdEmp(empUserBaseDTO);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 根据id查询用户详情
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("{id}")
  @ApiOperation("根据id查询用户详情")
  public RestMessage findById(@PathVariable("id")String id) {
    Assert.notNull(id,"id不能为空");
    UserProject userProject = userProjectService.getById(id);
    return RestBuilders.successBuilder().data(userProject).build();
  }

  /**
   * @Description: 根据card查询是否存在base
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("card/{card}")
  @ApiOperation("根据id查询用户详情")
  public RestMessage getByCard(@PathVariable("card")String card) {
    Assert.notNull(card,"身份证不能为空");
    EmpUserBase empUserBase = userProjectService.getByCard(card);
    return RestBuilders.successBuilder().data(empUserBase).build();
  }

  /**
   * @Description: 根据id查询用户详情(基础属性)
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("emp/{id}")
  @ApiOperation("根据id查询用户详情")
  public RestMessage findByIdEmp(@PathVariable("id")String id) {
    Assert.notNull(id,"id不能为空");
    EmpUserBaseDTO empUserBaseDTO = userProjectService.getByIdEmp(id);
    return RestBuilders.successBuilder().data(empUserBaseDTO).build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("list")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage queryListByPage(@RequestBody RequestModel<UserProjectDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserProjectDTO> record =  userProjectService.queryListByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询 黑名单使用
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("black/list")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage queryBlackListByPage(@RequestBody RequestModel<UserProjectDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserProjectDTO> record =  userProjectService.queryBlackListByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据班组id查询，不分页
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("group")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage queryByGroupId(@RequestBody UserProjectDTO userProjectDTO){
    List<EmpUserBase> record =  userProjectService.queryByGroupId(userProjectDTO);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，获取统计
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("count")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage count(@RequestBody UserProjectDTO userProjectDTO){
    Map<String,Long> map =  userProjectService.getCount(userProjectDTO);
    return RestBuilders.successBuilder().data(map).build();
  }

  /**
   * @Description: 根据条件，获取可以添加到项目的用户
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("baseUser")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage getBaseUsers(@RequestBody RequestModel<UserProjectDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<EmpUserBase> record =  userProjectService.getBaseUsers(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，导出用户用户
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("export")
  @ApiOperation("花名册导出")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "导出花名册")
  public void export(@RequestBody RequestModel<UserProjectDTO> requestModel, HttpServletRequest request, HttpServletResponse response) {
    requestModel.getPage().setSize(-1);
    IPage<UserProjectDTO> iPage = userProjectService.queryListByPage(requestModel);
    iPage.getRecords().forEach(r ->{
      //数据转换
      r.setGenderStr(Integer.valueOf(1).equals(r.getGender())?"男":"女");
      if (r.getGateStatus() == null){
        r.setGateStatusStr("未下发闸机");
      }else{
        r.setGateStatusStr(r.getGateStatus().intValue() == 1?"已下发闸机":"未下发闸机");
      }
      r.setStatusStr(Integer.valueOf(1).equals(r.getStatus())?"在岗":"离岗");
      r.setJoinTimeStr(new SimpleDateFormat("yyyy-MM-dd").format(r.getJoinTime()));
      r.setLeaveTimeStr(DateUtil.format(r.getLeaveTime(), DatePattern.NORM_DATE_PATTERN));
      r.setCertStr(r.getCertNum() > 0 ? "有" : "无");
      r.setBlackStr(r.getBlackNum() > 0 ? "是" : "否");
    });
    String keyValue = "姓名:userName,性别:genderStr,身份证号码:card,年龄:age,联系电话:telephone,工种:workType,班组:groupName," +
        "参建单位:companyName,在岗状态:statusStr,进场日期:joinTimeStr,退场日期:leaveTimeStr,闸机状态:gateStatusStr,证书:certStr,黑名单:blackStr";
    String title = "花名册";
    String fileName = title + ".xls";
    try {
      OutputStream outputStream = OutputStreamUtil
          .getOutputStream(request, response, fileName);
      ExcelTools.exportExcel(outputStream, keyValue, iPage.getRecords(), ExcelConstant.XLS, title);
      response.flushBuffer();
      outputStream.close();
    } catch (IOException e) {
      throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
    } catch (Exception e) {
      throw new RuntimeException("excel导出失败！" + e.getMessage());
    }
  }

  /**
   * 批量导入花名册(实名制)
   * type = 1 为覆盖
   */
  @PostMapping("importReal")
  @ApiOperation("批量导入")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage importRealExcel(@NotNull @RequestPart("file") MultipartFile file,Integer type)throws Exception {
    //记录日志
    if(file != null){
      String fileName = file.getOriginalFilename();
      LogHelper.setContent(LogOperateType.LABOL_REALNAME_PLATFORM_IMPORTREAL, fileName);
    }
    //获取当前时间的时间
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
    String key = "userProjectReal:"+formatter.format(calendar.getTime());
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    AsyncUtil.submitTask(key,() ->{
      ExcelResultDTO resultDTO;
      try {
        resultDTO = userProjectService.importExcel(file, type,tenantId,true);
      } catch (Exception e) {
        throw new BusinessException(e.getMessage());
      }
      return resultDTO;
    });
    return RestBuilders.successBuilder().data(key).build();
  }

  /**
   * 批量导入花名册(非实名制)
   * type = 1 为覆盖
   */
  @PostMapping("import")
  @ApiOperation("批量导入")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage importExcel(@NotNull @RequestPart("file") MultipartFile file,Integer type)throws Exception {
    //记录日志
    if(file != null){
      String fileName = file.getOriginalFilename();
      LogHelper.setContent(LogOperateType.LABOL_USER_BATCH_IMPORT, fileName);
    }
    //获取当前时间的时间
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
    String key = "userProject:"+formatter.format(calendar.getTime());
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    AsyncUtil.submitTask(key,() ->{
      ExcelResultDTO resultDTO = null;
      try {
        resultDTO = userProjectService.importExcel(file, type,tenantId,false);
      } catch (Exception e) {
        throw new BusinessException(e.getMessage());
      }
      return resultDTO;
    });
    return RestBuilders.successBuilder().data(key).build();
  }

  /**
   * @Description: 下载实名制平台导入模板
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("exportRealTemplate")
  @ApiOperation("下载模板")
  public void exportRealTemplate(HttpServletResponse response) throws IOException {
    try {
      Resource resource = resourceLoader.getResource("classpath:templates/real.xlsx");
      InputStream inputStream = resource.getInputStream();
      byte[] fileSource = IOUtils.toByteArray(inputStream);
      //防止对原数据进行操作
      byte[] fileBytes = Arrays.copyOf(fileSource, fileSource.length);
      String name = "real";
      //下载模板
      response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name,"UTF-8") + ".xlsx");
      response.setHeader("Content-Type", "application/vnd.ms-excel");
      response.setCharacterEncoding("UTF-8");
      response.getOutputStream().write(fileBytes);
      response.setContentLength(fileBytes.length);
    } finally {
      if (response.getOutputStream() != null) {
        response.getOutputStream().flush();
      }
    }
  }

  /**
   * 批量导入人员近照
   */
  @PostMapping("importPhoto")
  @ApiOperation("批量导入人员近照")
  @CommonOperateLogAnnotate(module = LogModule.LABOR_MANAGEMENT, desc = "")
  public RestMessage importPhoto(@NotNull @RequestPart("file") MultipartFile file,Integer type)
      throws Exception {
    //记录日志
    if(file != null){
      String fileName = file.getOriginalFilename();
      LogHelper.setContent(LogOperateType.LABOL_USER_BATCH_IMPORT_PHOTO, fileName);
    }
    //获取当前时间的时间
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
    String key = "userPhoto:"+formatter.format(calendar.getTime());
    List<UnzipFileVo> unzipFileVos = UnZipUtils.unzip(file, photoDir);
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    AsyncUtil.submitTask(key,() ->{
      ExcelResultDTO resultDTO;
      try {
        resultDTO = userProjectService.importPhoto(unzipFileVos,tenantId,type);
      } catch (Exception e) {
        throw new BusinessException(e.getMessage());
      }
      return resultDTO;
    });
    return RestBuilders.successBuilder().data(key).build();
  }

  /**
   * @Description: 下载模板
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("exportTemplate")
  @ApiOperation("下载模板")
  public void exportTemplate(HttpServletRequest request, HttpServletResponse response) {
    String title = "花名册";
    String fileName = title + ".xls";
    try {
      OutputStream outputStream = OutputStreamUtil
          .getOutputStream(request, response, fileName);
      String keyValue = "姓名(必填*):userName,性别(必填*):genderStr,民族(必填*):nation,"
          + "身份证号码(必填*):card,联系电话(必填*):telephone,参建单位(必填*):companyName,"
          + "班组(必填*):groupName,工种(必填*):workType";
      ExcelTools
          .exportExcel(outputStream, keyValue, UserProjectDTO.creatExcel(), ExcelConstant.XLSX,title);
      response.flushBuffer();
      outputStream.close();
    } catch (IOException e) {
      throw new RuntimeException("excel导出失败！IOException异常");
    } catch (Exception e) {
      throw new RuntimeException("excel导出失败！");
    }
  }

  /**
   * @Description: 根据条件，分页(不分页)查询人员在场情况
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("onAreas")
  @ApiOperation("根据条件，分页(不分页)查询人员在场情况")
  public RestMessage onAreasList(@RequestBody RequestModel<UserProjectDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserProjectDTO> record =  userProjectService.onAreasList(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 在场人数统计
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("onAreas/count")
  @ApiOperation("在场人数统计")
  public RestMessage onAreaCount(){
    Map<String, Integer> map =  userProjectService.onAreaCount();
    return RestBuilders.successBuilder().data(map).build();
  }

}

